# -*- coding: utf-8 -*-
"""
@Author  : lon91ong (lon91ong@gmail.com)
@Version : 0.9.9
"""
import falcon
from threading import Thread
from xml.etree.ElementTree import ElementTree, fromstring
from os import system, path
from base64 import b64encode
from re import search
from urllib.parse import quote
import requests
from sys import exit
from winreg import OpenKey, QueryValue, CloseKey, HKEY_CLASSES_ROOT

try:
    key = OpenKey(HKEY_CLASSES_ROOT,'Lab\shell\open\command')
    workpth = path.dirname(QueryValue(key,'').split('"')[1])
    CloseKey(key)
except:
    print('\n未找到注册表项, 请先执行安装!')
    exit(0)

system('mode con cols=52 lines=120')

# web服务
class Resource(object):
    curLab = ''
    labSort = '未分类'
    lablist = open('lablist.txt',mode='w+',encoding='utf-8')
    def on_get(self, req, resp, labfile):
        #print('URL:{}\nPath:{}'.format(req.url,req.path))
        print('LabID:{},LabName:{}'.format(self.curLab,labfile[:-4]))
        self.lablist.write('<Experiment Sort="{}" Name="{}" UpTime="2021-08-11T14:21:34" ID={} />\n'.format(self.labSort,labfile[:-4],self.curLab))
        
        self.curLab = labfile[:-4]
        resp.content_type = 'text/xml; charset=utf-8'
        #resp.data = ''
        resp.status = falcon.HTTP_400

    def on_post(self, req, resp):
        # post部分照搬pySvr
        resp.content_type = 'text/xml; charset=utf-8'
        #print('Path:', req.path)
        if req.path == '/BizService.svc':
            dataStr = '' # 响应数据
            # 响应文本预制
            respStr = '<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/"><s:Body><DoServiceResponse xmlns="http://www.ustcori.com/2009/10"><DoServiceResult xmlns:i="http://www.w3.org/2001/XMLSchema-instance"><Data i:nil="true"/><Message/><RecordCount>0</RecordCount><Status>Success</Status></DoServiceResult></DoServiceResponse></s:Body></s:Envelope>'
            xmls = req.stream.read().decode('utf-8') #req.media
            method = search(r'(?<=<MethodName>).*(?=</MethodName>)',xmls)[0]
            #print('Method:',method)
            null = None; false = False
            if method == 'FindNewExamRoom':
                labroom = tree.parse(workpth + '/Download/download.xml')[0].attrib
                dataStr = '<DataString>{"ROOMID":'+labroom['ID']+',"VERSION":"'+labroom['Version']+'"}</DataString>'
            elif method == 'FindByLABID':
                labid = fromstring(xmls).findall(".//{http://schemas.microsoft.com/2003/10/Serialization/Arrays}Value")[0].text
                self.curLab=labid
                try: # online
                    headers = {'Content-Type': 'text/xml; charset=utf-8','SOAPAction': 'http://www.ustcori.com/2009/10/IBizService/DoService','Host': 'aryun.ustcori.com:9542'}
                    xmls = fromstring(requests.post('http://aryun.ustcori.com:9542'+req.path,data=xmls,headers=headers).text)
                    #print('Online Mode!')
                    dataStr = '<DataString>{}</DataString>'.format(xmls.findall(".//{http://www.ustcori.com/2009/10}DataString")[0].text)
                except: # offline
                    lab = labroot.findall('.//Experiment[@ID='+labid+']')[0].attrib
                    print('实验:',lab['Name'],'分类:',lab['Sort'])
                    self.labSort = lab['Sort']
                    dataStr = '<DataString>[{"LabID":'+labid+',"LABNAME":"'+lab['Name']+'","LABTYPEID":null,"LABTYPENAME":"'+lab['Sort']+'","INTRODUTION":"","CONTENT":null,"THEORY":null,"INSTRUMENT":null,"QualifiedTime":null,"LabFileUrl":"'+lab['Name']+'.lab","LabUpTime":null,"SourceFileUrl":null,"SourceUpTime":null,"UpTime":"'+lab['UpTime']+'","UPUSER":null,"LabWeight":null,"ReportWeight":null,"ReportFileUrl":null,"ReportUpTime":null}]</DataString>'
                
            elif method == 'ucControlMethod':
                dataStr = '<DataString>192</DataString>'
            elif method == 'SetLabTimeRecord':
                dataStr = '<DataString>9000</DataString>'
            elif method == 'AddOneToLabFileDownLoadCount':
                dataStr = '<DataString>"1"</DataString>'
            elif method == 'JFIsAccess':
                dataStr = '<DataString>""</DataString>'
            insp = respStr.index('<Message/>') # 定位插入点
            resp.data = bytes(respStr[:insp] + dataStr + respStr[insp:],encoding='utf-8')
        elif req.path == '/ServiceAPI/SetLabTimeRecordStart':
            resp.data = '7777'.encode('utf-8')
        elif req.path == '/ServiceAPI/UpdateRecord':
            resp.data = '1'.encode('utf-8')
        else:   # /FileTransfer.svc
            resp.data = '<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/"><s:Body><UploadFileResponse xmlns="http://tempuri.org/"/></s:Body></s:Envelope>'.encode('utf-8')
        resp.status = falcon.HTTP_200

class Serv(Thread):
    def __init__(self, threadID, mRes, svrp):
        Thread.__init__(self)
        self.threadID = threadID
        self.port = svrp
        self.svrRes = mRes
        self.app = falcon.API()

    def run(self):
        from waitress import serve
        apilst = ['/Upload/lab/{labfile}','/BizService.svc','/ServiceAPI/SetLabTimeRecordStart','/ServiceAPI/UpdateRecord','/FileTransfer.svc']
        for apistr in apilst: self.app.add_route(apistr, self.svrRes)
        print("\n服务端启动...\n")
        try:
            serve(self.app, listen = '127.0.0.1:'+self.port)
        except:
            print('错误:网络端口({})可能被占用!'.format(self.port))
            exit(0)
        
def cleanDir(dir, sname):
    from os import listdir, rmdir, remove

    for dire in listdir(dir):
        dire = path.join(dir,dire)
        if path.isfile(dire):
            if sname in path.basename(dire) or path.basename(dire)[:-4] in sname:
                remove(dire)
                #print('删除文件:'+path.basename(dire))
                if not listdir(path.dirname(dire)):
                    rmdir(path.dirname(dire)) #删除空路径
        else:
            cleanDir(dire,sname) #递归子目录

if __name__ == '__main__':
    from subprocess import Popen
    from time import sleep
    from sys import argv
    from itertools import chain
    falRes = Resource()
    port = '9650' if len(argv)==1 else argv[1] #服务端口
    mySvr=Serv(1,falRes,port)
    mySvr.daemon = True #服务线程与主线程共存亡
    mySvr.start()
    exeProg = workpth+r'\Download\Updata\WebLabClient.exe'
    sleep(2)
    if(mySvr.is_alive()):
        print("本地没有的实现项目如下:")
        #现有的实验分布在356~396,500~512区间; 本地已有的不显示
        for labId in chain(range(355,400),range(500,520)):
            burl = bytes('/'+str(labId)+'/127.0.0.1/'+port+'/userid/op/1/2',encoding='utf-8')
            href='lab://{}/'.format(b64encode(burl).decode('utf-8'))
            pp = Popen([exeProg, href])
            #print('LabID:',labId)
            sleep(1)
            pp.kill()
            sleep(0.5)
            if not falRes.curLab.strip('"').isdigit():
                cleanDir(workpth+r'\Download\Updata\Download', falRes.curLab)
        print("\n项目查询完毕!")
    else:
        print("\n服务端启动失败, 查询程序退出!")
    falRes.lablist.close()